package com.rbac.controller;

import com.rbac.common.Result;
import com.rbac.dto.LoginRequest;
import com.rbac.dto.LoginResponse;
import com.rbac.entity.SysMenu;
import com.rbac.entity.SysUser;
import com.rbac.service.SysUserService;
import com.rbac.utils.JwtUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * 认证控制器
 *
 * @author rbac-system
 * @since 2024-01-01
 */
@Slf4j
@RestController
@RequestMapping("/auth")
@Api(tags = "认证管理")
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private SysUserService userService;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Value("${jwt.expiration}")
    private Long expiration;

    @PostMapping("/login")
    @ApiOperation("用户登录")
    public Result<LoginResponse> login(@Valid @RequestBody LoginRequest loginRequest) {
        try {
            // 认证用户
            Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(
                    loginRequest.getUsername(),
                    loginRequest.getPassword()
                )
            );

            SecurityContextHolder.getContext().setAuthentication(authentication);
            // 生成JWT token
            UserDetails userDetails = (UserDetails) authentication.getPrincipal();
            String token = jwtUtils.generateToken(userDetails);

            // 获取用户信息
            SysUser user = userService.getUserWithRolesAndPermissions(loginRequest.getUsername());
            if (user == null) {
                return Result.error("用户不存在");
            }
            // 获取用户菜单
            List<SysMenu> menus = userService.getMenusByUserId(user.getId());

            // 构建响应
            LoginResponse response = new LoginResponse();
            response.setAccessToken(token);
            response.setExpiresIn(expiration);
            response.setUserId(user.getId());
            response.setUsername(user.getUsername());
            response.setNickname(user.getNickname());
            response.setEmail(user.getEmail());
            response.setAvatar(user.getAvatar());
            response.setRoles(user.getRoles());
            response.setMenus(menus);

            return Result.success("登录成功", response);
        } catch (Exception e) {
            return Result.error("用户名或密码错误");
        }
    }

    @PostMapping("/logout")
    @ApiOperation("用户登出")
    public Result<String> logout() {
        SecurityContextHolder.clearContext();
        return Result.success("登出成功");
    }

    @GetMapping("/user/info")
    @ApiOperation("获取当前用户信息")
    public Result<LoginResponse> getCurrentUser() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null || !authentication.isAuthenticated()) {
            return Result.error(401, "未登录");
        }

        String username = authentication.getName();
        SysUser user = userService.getUserWithRolesAndPermissions(username);
        if (user == null) {
            return Result.error("用户不存在");
        }

        // 获取用户菜单
        List<SysMenu> menus = userService.getMenusByUserId(user.getId());

        // 构建响应
        LoginResponse response = new LoginResponse();
        response.setUserId(user.getId());
        response.setUsername(user.getUsername());
        response.setNickname(user.getNickname());
        response.setEmail(user.getEmail());
        response.setAvatar(user.getAvatar());
        response.setRoles(user.getRoles());
        response.setMenus(menus);

        return Result.success(response);
    }
}
